#ifndef YHAIDA_UTILS_H
#define YHAIDA_UTILS_H
#include <pthread.h>
#include <string.h>
#include <string>
#include <sys/syscall.h>
#include <unistd.h>
#include <iostream>
#include <algorithm>
#include <cassert>
#include <type_traits>
namespace yhaida
{
    inline void memZero(void* p, size_t n)
    {
        memset(p, 0, n);
    }

    namespace Utils
    {
        class nocapyable
        {
        public:
            nocapyable(const nocapyable &) = delete;
            nocapyable &operator=(const nocapyable &) = delete;

        protected:
            nocapyable() = default;
            ~nocapyable() = default;
        };
        // implicit_cast用于向上转型（子类指针–>父类指针）；
        template <typename To, typename From>
        inline To implicit_cast(From const &f)
        {
            return f;
        }

        // down_cast用于向下类型转换（父类指针–>子类指针）；
        template <typename To, typename From> // use like this: down_cast<T*>(foo);
        inline To down_cast(From *f)          // so we only accept pointers
        {
            // Ensures that To is a sub-type of From *.  This test is here only
            // for compile-time type checking, and has no overhead in an
            // optimized build at run-time, as it will be optimized away
            // completely.
            if (false)
            {
                implicit_cast<From *, To>(0);
            }

#if !defined(NDEBUG) && !defined(GOOGLE_PROTOBUF_NO_RTTI)
            assert(f == NULL || dynamic_cast<To>(f) != NULL); // RTTI: debug mode only!
#endif
            return static_cast<To>(f);
        }
    }

    namespace CurrentThread
    {
        extern __thread pid_t currend_tid;
        extern __thread const char *currend_thread_name;
        pid_t tid();
        const char *name();
        bool isMainThread();
    }

    namespace Detail
    {
        const int kSmallBuffer = 1000;        // 1MB
        const int kLargeBuffer = 4000 * 1000; // 4MB

        template <int SIZE>
        class FixedBuffer : Utils::nocapyable
        {
        public:
            FixedBuffer() : _cur(_data)
            {
                setCookie(cookieStart);
            }
            ~FixedBuffer()
            {
                setCookie(cookieEnd);
            }
            void setCookie(void (*cookie)()) { cookie_ = cookie; }

            //写数据
            void push_data(const char *buff, int len)
            {
                if (intVail() > len)
                {
                    memcpy(_cur, buff, len);
                    _cur += len;
                }
                //扩容
            }

            //当前指针
            char *current() { return _cur; }
            //尾指针
            const char *end() const { return _data + sizeof(_data) / sizeof(char); }

            //是否有效
            int intVail() const { return static_cast<int>(end() - _cur); }
            //返回数据
            const char *data() const { return _data; }

            //返回长度
            int length() const { return _cur - _data; }
            //移动当前指针
            void addLength(size_t length) { _cur += length; }

            //当前指针置于首指针
            void reset() { _cur = _data; }
            //置零
            void setZero() { memset(_data, 0, sizeof(_data)); }

            // for used by GDB
            const char *debugString();

            // for used by unit test
            // 把char转换位string
            std::string toString() const { return std::string(_data, length()); }

        private:
            // Must be outline function for cookies.
            static void cookieStart();
            static void cookieEnd();

            void (*cookie_)();

            char *_cur;
            char _data[SIZE];
        };

        class T
        {
        public:
            T(const char *str, int len) : _str(str), _length(len)
            {
                // std::cout<<"test:"<<_str<<" "<<strlen(_str)<<" "<<_length<<std::endl;
                assert(strlen(_str) == _length);
            }
            ~T() = default;

            const char *_str;
            const size_t _length;
        };
    }

    namespace Detail
    {
        class File : yhaida::Utils::nocapyable
        {
        public:
            explicit File(const std::string &filename);
            ~File();

            void append(const char *str, const size_t length);
            void flush();

            const size_t getWriteBytes() const;

        private:
            size_t write(const char *str, size_t length);

        private:
            FILE *_fp;
            char _buff[64 * 1024];
            size_t _writtenBytes;
        };
    }

    namespace Utils
    {
        class any final
        {
        protected:
            //基类
            class ValueBase
            {
            public:
                virtual void *getValue() = 0;
                virtual const char *getType() = 0;
                virtual ValueBase *clone() = 0;
                virtual ~ValueBase(){};
            };

            //模板派生类
            template <typename T>
            class Value : public ValueBase
            {
            private:
                T _value;

            public:
                Value(const T &val) : _value(val)
                {
                }
                Value(T &&val) : _value(std::move(val))
                {
                }
                virtual void *getValue()
                {
                    return &_value;
                }
                virtual const char *getType()
                {
                    return typeid(T).name();
                }
                virtual ValueBase *clone()
                {
                    return new Value<T>(_value);
                }
            };

        public:
            any() : _value(nullptr)
            {
            }
            //重载完美转发需要使用enable_if避免准确重载
            template <typename T, typename = typename std::enable_if<
                                      //除了any类型之外的类型，排序下面两种拷贝函数
                                      !std::is_same<any, typename std::decay<T>::type>::value>::type>
            explicit any(T &&val)
                // typename std::decay<T>::type去除
                //类型中的一些特性，比如引用、常量、volatile，但是注意不包括指针特性
                : _value(new Value<typename std::decay<T>::type>(val))
            {
            }
            any(const any &other)
                : _value(other.empty() ? nullptr : other._value->clone())
            {
            }
            any(any &&other)
                : _value(other.empty() ? nullptr : std::move(other._value))
            {
                other._value = nullptr;
            }
            virtual ~any()
            {
                if (_value)
                {
                    delete _value;
                }
            }
            any &swap(any &other)
            {
                std::swap(_value, other._value);
                return *this;
            }
            // any& operator=(any&other);//形参一定是引用，传值的话会造成循环赋值

            template <typename T>
            any &operator=(T &&val)
            {
                any temp(std::forward<T>(val));
                this->swap(temp);
                return *this;
            }

            bool empty() const
            {
                return _value == nullptr;
            }

            const char *getValueType()
            {
                if (_value)
                {
                    return _value->getType();
                }
                return nullptr;
            }

            ValueBase *getValue()
            {
                return _value;
            }

        private:
            ValueBase *_value;
        };

        template <typename T>
        T *any_cast(any *other)
        {
            if (typeid(T).name() == other->getValue()->getType())
            {
                return reinterpret_cast<T *>(other->getValue()->getValue());
            }
            else
            {
                throw std::runtime_error("bad_any_cast");
            }
        }
        template <typename T>
        T &any_cast(any &other)
        {
            if (typeid(T).name() == other.getValue()->getType())
            {
                return *reinterpret_cast<T *>(other.getValue()->getValue());
            }
            else
            {
                throw std::runtime_error("bad_any_cast");
            }
        }
    }
}

#endif